package zsl.output;

import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;

import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import zsl.utils.MergeTimeInfo;
import zsl.utils.RunningTimeInfo;
import zsl.utils.TAInfo;
import zsl.utils.TAInfo.TAStepInfo;
import zsl.utils.TopKInfo;
import zsl.utils.WordCount;
import zsl.utils.WordCountList;

public class ExcelWriter {
	private static final String[] RUNNING_TIME_INFO_TITLES = {"ListNum", /*"Depth*ListNum^2",*/ "TATime", "MergeTime", "Total"/*, "AccessPercent"*/};
	private static final String[] TA_INFO_TITLES = {"Depth", "threshold", "curKValue"};
	private Workbook workbook;
	private static final String[] MERGE_INFO_TITLES = {"listNum", "mergeTime", "sortTime", "totalTime", "addedMerge", "addedSort"};
	public ExcelWriter() {
		workbook = new XSSFWorkbook();
	}
	
	public void addRunningTimeInfoSheet(String sheetName, List<RunningTimeInfo> infos, List<TAInfo> taInfos) {
		Sheet sheet = workbook.createSheet(sheetName);
		
		// add title to sheet
		addTitle(RUNNING_TIME_INFO_TITLES, sheet);
		
		// add content
		Iterator<RunningTimeInfo> iterator = infos.iterator();
//		Iterator<TAInfo> taIterator = taInfos.iterator();
		int rowNum = 1;
		Row row;
		while (iterator.hasNext()) {
			RunningTimeInfo runningTimeInfo = iterator.next();
			//add a new row
			row = sheet.createRow(rowNum);
			//add list number, ta time, merge time and total time to the row
//			TAInfo taInfo = taIterator.next();
			row.createCell(0).setCellValue(runningTimeInfo.getListNum());
//			row.createCell(1).setCellValue(taInfo.getMaxDepth()*runningTimeInfo.getListNum()*runningTimeInfo.getListNum());
			row.createCell(1).setCellValue(runningTimeInfo.getTaTime());
			row.createCell(2).setCellValue(runningTimeInfo.getMergeTime());
			row.createCell(3).setCellValue(runningTimeInfo.getTaTime()+ runningTimeInfo.getMergeTime());
//			row.createCell(5).setCellValue(taInfo.getAccessDepth()/(double)taInfo.getMaxDepth());
			
			rowNum++;
		}
	}
	
	public void addTaInfoSheet(String sheetName, TAInfo taInfo){
		Sheet sheet = workbook.createSheet(sheetName);
		addTitle(TA_INFO_TITLES, sheet);
		
		//add content
		int numOfRows = taInfo.getStepInfoSize();
		TAStepInfo stepInfo;
		Row row;
		for (int i = 0, rowNum = 1; i < numOfRows; i++, rowNum++) {
			row = sheet.createRow(rowNum);
			stepInfo = taInfo.getStepInfo(i);
			row.createCell(0).setCellValue(stepInfo.getDepth());
			row.createCell(1).setCellValue(stepInfo.getThreshold());
			row.createCell(2).setCellValue(stepInfo.getLeastK());
		}
	}
	
	public void addMergeTimeSheet(String sheetName, List<MergeTimeInfo> mergeTimeList ){
		Sheet sheet = workbook.createSheet(sheetName);
		addTitle(MERGE_INFO_TITLES, sheet);
		
		//add content
		int numOfRows = mergeTimeList.size();
		Row row;
		MergeTimeInfo mergeInfo;
		for (int i = 0, rowNum = 1; i < numOfRows; i++, rowNum++) {
			row = sheet.createRow(rowNum);
			mergeInfo = mergeTimeList.get(i);
			row.createCell(0).setCellValue(mergeInfo.getListNum());
			row.createCell(1).setCellValue(mergeInfo.getMergeTime());
			row.createCell(2).setCellValue(mergeInfo.getSortTime());
			row.createCell(3).setCellValue(mergeInfo.getTotal());
			row.createCell(4).setCellValue(mergeInfo.getAddedMergeTime());
			row.createCell(5).setCellValue(mergeInfo.getAddedSortTime());
		}
	}
	
	public void addCountDistributionSheet(String sheetName, Vector<WordCountList> lists){
		//generate titles = list1, list2
		String[] titles = new String[lists.size()];
		for (int i = 0; i < titles.length; i++) {
			titles[i] = "list"+i;
		}
		// add titles
		Sheet sheet = workbook.createSheet(sheetName);
		addTitle(titles, sheet);
		// add content
		int numOfRows = lists.get(0).size();
		int numOfCellsPerRow = lists.size();
		Row row;
		for (int i = 0, rowNum = 1; i < numOfRows; i++, rowNum++) {
			row = sheet.createRow(rowNum);
			for (int j = 0; j < numOfCellsPerRow; j++) {
				row.createCell(j).setCellValue(lists.get(j).get(i).getCount());
			}
		}
	}
	
	public void addTopKDistributionSheet(String sheetName, Vector<WordCountList> lists, List<WordCount> topKList){
		int numOfCellPerRow = lists.size()*2+1;
		
		String[] titles = new String[numOfCellPerRow];
		titles[0] = "words";
		for (int i = 1; i < titles.length; i++) {
			titles[i] = "list"+(i-1)/2;
			if (i % 2 == 1) {
				titles[i] += "-pos";
			}else {
				titles[i] += "-count";
			}
		}
		
		Sheet sheet = workbook.createSheet(sheetName);
		addTitle(titles, sheet);
		//add content
		int numOfRows = topKList.size();
		Row row;
		String word;
		int listNum;
		TopKInfo topKInfo;
		for (int i = 0, rowNum = 1; i < numOfRows; i++, rowNum++) {
			row = sheet.createRow(rowNum);
			word = topKList.get(i).getWord();
			row.createCell(0).setCellValue(word);
			for (int j = 1; j < numOfCellPerRow; j += 2) {
				listNum = (j-1)/2;
				topKInfo = getTopKInfo(lists.get(listNum), word);
				row.createCell(j).setCellValue(topKInfo.getPos());
				row.createCell(j+1).setCellValue(topKInfo.getWc().getCount());
			}
		}
	}
	
	private TopKInfo getTopKInfo(WordCountList list, String word){
		int size = list.size();
		WordCount wordCount;
		for (int i = 0; i < size; i++) {
			 wordCount = list.get(i);
			if (wordCount.getWord().equals(word)) {
				return new TopKInfo(i, wordCount);
			}
		}
		System.err.println("should not reach here!!!");
		return null;
	}
	
	private void addTitle(String[] titles, Sheet sheet) {
		Row headerRow = sheet.createRow(0);
		for (int i = 0; i < titles.length; i++) {
			headerRow.createCell(i).setCellValue(titles[i]);
		}
	}
	
	public void write2Excel(String fileName) throws IOException{
		FileOutputStream fos = new FileOutputStream(fileName);
		workbook.write(fos);
		fos.close();
	}
	
	
	
	public static void main(String[] args) throws IOException {
		final String[] TITLES = {"listNum", "taTime", "mergeTime", "total"}; 
		List<RunningTimeInfo> list = new ArrayList<>();
		list.add(new RunningTimeInfo(1, 123, 222));
		list.add(new RunningTimeInfo(2, 123, 444));
		ExcelWriter writer = new ExcelWriter();
		writer.addRunningTimeInfoSheet("my sheet", list, null);
		writer.write2Excel("testWrite.xlsx");
	}
}
